home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / TCOMMPRO.TXT / XMODEM1.C < prev    next >
Text File  |  1987-01-14  |  26KB  |  1,090 lines

  1. /*
  2.  
  3.     xmodem1.c
  4.  
  5.  
  6.     8/1/85
  7.  
  8.  
  9.     A version of Ward Christensen's MODEM program modified
  10.     by Larry Jordan Associates to include XMODEM features
  11.     and to provide compatibility with TCOMM.
  12.  
  13.     This file contains the main Xmodem functions.
  14.  
  15.  
  16.     Copyright (c) 1984, 1985 Larry Jordan Associates
  17. */
  18.  
  19.  
  20.  
  21. #include    <stdio.h>    /* Lattice header */
  22. #include    <gleafs.h>    /* Greenleaf header */
  23. #include    <ibmkeys.h>    /* Greenleaf header */
  24. #include    <asic.h>    /* Greenleaf header */
  25. #include    <timedate.h>    /* Greenleaf header */
  26. #include    <disk.h>    /* Greenleaf header */
  27. #include    <protocol.h>    /* Xmodem header provided on disk */
  28. #include    <function.h>    /* Xmodem header provided on disk */
  29. #include    <xfer.h>    /* Xmodem header provided on disk */
  30. #include    <ibmpcio.h>    /* Xmodem header provided on disk */
  31.  
  32.  
  33.     char  packet[134];
  34.     char  xmode,xdirfile[60],xfilenam[60];
  35.     char  kparity[10];
  36.     char  *comparms,portnum[60],*menudrv;
  37.     char  recvbuff[512],txbuff[512];
  38.     char  retstr[80],filedate[80];
  39.  
  40.     long  strtout,timelog;
  41.     long fbytes,fblocks;
  42.     long xfertime;
  43.     long  goodbyte;
  44.  
  45.     float xfactor = 1.0;
  46.  
  47.     int   cfgcolor,display,local,defsec,len,graphics;
  48.     int   monitor,cleared,attrib;
  49.     int   duplex,crtecho,portsel,
  50.           port,bps,parity,wordlen,stopbits,comport;
  51.  
  52.  
  53.  
  54. /* Copyright (c) 1984, 1985 Larry Jordan Associates  */
  55.  
  56.  
  57. /*
  58.  *   main
  59.  *
  60.  *
  61.  *
  62.  */
  63.  
  64. main()
  65. {
  66.     extern int wordlen;
  67.     char message[80];
  68.  
  69.     if (xferread() == FALSE || (makebuff() == ERROR))  /* if not file xfer info on disk or cannot make comm buffer, exit */
  70.           {
  71.           endxm();
  72.           }
  73.     if ( wordlen == 7)    /* if not 8 data bits, tell user nono and exit */
  74.           {
  75.           stccpy(message,XBIT,79);
  76.           prosay(23,0,message);
  77.           asiputc(port,CR);
  78.           asiputc(port,LF);
  79.           asiputs(port,message);
  80.           asiputc(port,CR);
  81.           asiputc(port,LF);
  82.           asiputc(port,CR);
  83.           asiputc(port,LF);
  84.           delay(30);
  85.           endxm();
  86.           }
  87.     xmodem();   /* looks good so far, lets do it! */
  88.     endxm();    /* shut down Xmodem buffer and go back */
  89. }
  90.  
  91.  
  92.  
  93.  
  94. int xmodem()
  95. {
  96.     extern char xmode,xdirfile[60],xfilenam[60];
  97.     char vline[120]; /* debug only */
  98.  
  99.     switch (xmode)
  100.         {
  101.  
  102.         case 's':
  103.             sxmodem(xdirfile);           /* send file */
  104.             break;
  105.  
  106.         case 'r':
  107.             prouinfo(xdirfile,"Xmodem",128);    /* display file upload info */
  108.             rxmodem(xdirfile);            /* receive file */
  109.             break;
  110.         default:
  111.             return(ERROR);            /* if you don't tell me what to do, I will just go home */
  112.         }
  113.     return(TRUE);                    /* we've finsihed this one */
  114. }
  115.  
  116.  
  117.  
  118. /*
  119. *  sxmodem
  120. *
  121. *  send a file to the caller
  122. *
  123. *
  124. *
  125. */
  126.  
  127. int sxmodem(dirfile)
  128. char *dirfile;
  129. {
  130.  
  131.     extern    long int strtout,timelog;
  132.     extern long fbytes,fblocks;
  133.     extern long    goodbyte;
  134.     extern    char    retstr[80],packet[134];
  135.     extern int port;
  136.     char    sector[SECSIZE], chrhldr[10];
  137.     char    vline[120],sechar,oldpack[134];
  138.     int    first;
  139.     int    foo;
  140.     int    rtrn,i;
  141.     int    timeout;
  142.     int    index, errorcnt,checksum,errortot;
  143.     char    blockcnt;
  144.     int    sectot;
  145.     int    percent;
  146.     long    totbyte;
  147.  
  148.     int eoxmfile = FALSE;
  149.     int endfile = FALSE;
  150.  
  151.  
  152.     if((foo = open(dirfile,0x8000)) == -1)           /* open for read only */
  153.         {
  154.         close(foo);
  155.         return(FALSE);
  156.         }
  157.     prodinfo(dirfile,foo,"Xmodem",128);         /* display download info */
  158.  
  159.     errorcnt = 0;
  160.     errortot = 0;
  161.     blockcnt = 1;
  162.     sectot = 1;
  163.     goodbyte = 0L;
  164.     totbyte = 0L;
  165.  
  166.     timeout=SENTIMOUT;
  167.     clearmsg();
  168.     prosay(19,23,"Holding for start ");
  169.  
  170.     eatbuf();                 /* flush serial port of garbage */
  171.  
  172.     strtout = totsec();                   /* set start time */
  173.     while(TRUE)
  174.       {
  175.           if((rtrn = readbyte(30)) != TIMEOUT)  /* wait for caller's NAK */
  176.           {
  177.             if(retstr[0] == NAK)
  178.                 {
  179.                 clearmsg();
  180.                 prosay(19,23,"Transfer initiated ");
  181.                 break;
  182.                 }
  183.             else if (retstr[0] == CTRLX)  /* caller wants abort? */
  184.                 {
  185.                 endtalk(foo,2);
  186.                 return(FALSE);
  187.                 }
  188.             else if (rtrn == ESC)           /* SYSOP wants abort? */
  189.                 {
  190.                 endtalk(foo,1);
  191.                 return(ERROR);
  192.                 }
  193.             else
  194.                  {
  195.                  ++errorcnt;
  196.                  if( !(errorcnt % 3 )) clearmsg();
  197.                  if (errorcnt == MAXERRORS)
  198.                   {
  199.                   endtalk(foo,4);
  200.                   return(ERROR);
  201.                   }
  202.                  }
  203.             }
  204.         if (toolong(timeout))  /* caller waited too long, end Xmodem */
  205.             {
  206.             endtalk(foo,5);
  207.             return(FALSE);
  208.             }
  209.         if (!carrier())         /* watch for that modem carrier */
  210.             {
  211.             close(foo);
  212.             return(ERROR);
  213.             }
  214.         if (asikbhit())               /* did SYSOP hit key? */
  215.             {
  216.               if ( getch() == ESC )
  217.               {
  218.                  clearmsg();
  219.                  endtalk(foo,1);
  220.                  return(ERROR);
  221.                 }
  222.              }
  223.        }
  224.  
  225.     sechar = sectot & 255;
  226.  
  227.     eoxmfile = makepack(foo,sechar);   /* create first packet */
  228.  
  229.     while(TRUE)                 /* outside while for new block */
  230.         {
  231.  
  232.         errorcnt = 0;
  233.  
  234.         clearmsg();
  235.  
  236.         if (eoxmfile == 0) break;           /* no more bytes */
  237.  
  238.         if (eoxmfile < 128) endfile = TRUE;     /* a few more bytes */
  239.  
  240.         for(i = 0; i < 134; i++)
  241.             oldpack[i] = packet[i];
  242.  
  243.         first = TRUE;
  244.  
  245.         totbyte = goodbyte;
  246.  
  247.         eatbuf();                   /* flush garabage */
  248.  
  249.         while (TRUE)           /* inside while for current block */
  250.             {
  251.             if (asikbhit())      /* always let SYSOP get out */
  252.                 {
  253.                 if ( getch() == ESC)
  254.                     {
  255.                     endtalk(foo,1);
  256.                     return(ERROR);
  257.                     }
  258.                 }
  259.  
  260.             sprintf(vline,"Sending block # %d ",sectot);
  261.             prosay(19,23,vline);      /* tell SYSOP where we are */
  262.  
  263.             if (strput(oldpack) == TRUE)     /* send packet to caller */
  264.                {
  265.                if (first && !endfile)   /* first time around for this packet */
  266.                 {
  267.                 sechar = (sectot+1) & 255;
  268.                 eoxmfile = makepack(foo,sechar);   /* create packet */
  269.                 first = FALSE;
  270.                 }
  271.  
  272.                while (!istxempty(port));
  273.  
  274.                eatbuf();               /* flush garabage */
  275.  
  276.                if((rtrn = readbyte(15)) == TIMEOUT) /* wait for caller response */
  277.                 {
  278.                 endtalk(foo,5);
  279.                 return(ERROR);
  280.                 }
  281.                }
  282.             if(retstr[0] == ACK)         /* did Sam like packet? */
  283.                 {
  284.                 prosay(19,45,"- verified"); /* make SYSOP feel good */
  285.                 sprintf(vline,"%-4.4s","0   ");
  286.                 prosay(14,61,vline);
  287.                 sprintf(vline,"%d",sectot);
  288.                 prosay(12,61,vline);
  289.                 percent = (totbyte * 1.0)/fbytes * 100.0;
  290.                 sprintf(vline,"%-3d   ",percent);
  291.                 prosay( 8,61,vline);
  292.                 sprintf(vline,"%ld",totbyte);
  293.                 prosay(10,61,vline);
  294.                 percent = (errortot * 1.0)/sectot * 100.0;
  295.                 if (percent > 100) percent = 100;
  296.                 sprintf(vline,"%-3d   ",percent);
  297.                 prosay(16,61,vline);
  298.                 ++sectot;
  299.                 break;
  300.                 }
  301.  
  302.             else if (retstr[0] == CTRLX)  /* caller wants abort? */
  303.                 {
  304.                 endtalk(foo,2);
  305.                 return(FALSE);
  306.                 }
  307.  
  308.             else if(rtrn == ESC)           /* SYSOP wants abort? */
  309.                 {
  310.                 endtalk(foo,1);
  311.                 return(ERROR);
  312.                 }
  313.  
  314.             else if(!carrier())      /* did modem carrier drop? */
  315.                 {
  316.                 close(foo);
  317.                 return(ERROR);
  318.                 }
  319.             else        /* default is error--no need to check NAK */
  320.                 {
  321.                 prosay(19,45,"- transmission error");  /* caller said bad packet */
  322.                 ++errorcnt;
  323.                 ++errortot;     /* we count that against you */
  324.                 sprintf(vline,"%d   ",errorcnt);
  325.                 prosay(14,61,vline);
  326.                 sprintf(vline,"%d   ",errortot);
  327.                 prosay(14,25,vline);
  328.                 percent = (errortot * 1.0)/sectot * 100.0;
  329.                 if (percent > 100) percent = 100;
  330.                 sprintf(vline,"%-3d   ",percent);
  331.                 prosay(16,61,vline);
  332.                 prosay(16,25,"Receiver");
  333.                 clearmsg();
  334.                 if(errorcnt > MAXERRORS)
  335.                     {
  336.                     endtalk(foo,4);
  337.                     return(ERROR);
  338.                     }
  339.                 delay(10);          /* delay .1 sec */
  340.                 eatbuf();          /* flush garabage */
  341.                 }
  342.             }        /* end of inside while */
  343.  
  344.         if(endfile)  break;    /* looks like the end */
  345.  
  346.         }     /* end of outside while */
  347.  
  348.     close(foo);
  349.     errorcnt = 0;
  350.  
  351.     clearmsg();
  352.  
  353.     while (TRUE)
  354.         {
  355.         clearmsg();
  356.         prosay(19,23,"Sending EOT ");
  357.         chrput(EOT);             /* send Xmodem end of file mark */
  358.         eatbuf();
  359.         if((rtrn = readbyte(15)) == TIMEOUT )
  360.             {
  361.             chrput(CAN);  /* caller did not respond, cancel xfer */
  362.             clearmsg();
  363.             prosay(19,23,ABORTF);
  364.             prosay(19,40,ABORTEOF);
  365.             return(ERROR);
  366.             }
  367.         else if (rtrn == ESC) return(ERROR); /* SYSOP could not wait and aborted? */
  368.         if(retstr[0] == ACK)             /* did Sam get that EOF? */
  369.             {
  370.             prosay(19,33," - verified");
  371.             break;
  372.             }
  373.         if(!carrier())
  374.             {
  375.             return(ERROR);
  376.             }
  377.         ++errorcnt;
  378.         if(errorcnt > MAXERRORS)
  379.             {
  380.             clearmsg();
  381.             prosay(19,23," ** Transmission improperly completed");
  382.  
  383.             endtalk(foo,4);
  384.             return(ERROR);
  385.             }
  386.         prosay(19,33," - acknowledge error");
  387.  
  388.         }
  389.     clearmsg();
  390.     prosay(19,23,"Transmission completed properly");
  391.  
  392.     sizewrit(dirfile,goodbyte);
  393.  
  394.     return(TRUE);
  395.  
  396. }
  397.  
  398.  
  399. /*
  400.  *  makepack()
  401.  *
  402.  *  make the next Xmodem packet to send
  403.  *
  404.  *  Returns: TRUE if end of file encountered during read
  405.  *         FALSE if not end of file read
  406.  *
  407.  */
  408. bool makepack(foo,blockcnt)
  409. int foo;
  410. char blockcnt;
  411. {
  412.  
  413.     extern    char    packet[134];
  414.     extern    long    goodbyte;
  415.     char    sector[SECSIZE];
  416.     int    bytesget;
  417.     int    index,checksum,eoxmfile,n;
  418.  
  419.  
  420.            packet[0] = SOH;           /* here is our header */
  421.            packet[1] = blockcnt;           /* the block number */
  422.            packet[2] = ~blockcnt;        /* the block number compliment */
  423.  
  424.         checksum = 0;
  425.  
  426.         bytesget=read(foo,sector,128); /* get next 128 byte block from disk */
  427.  
  428.         goodbyte = goodbyte + (long)bytesget; /* how many do we have total */
  429.  
  430.         if (bytesget == 0) return(bytesget);  /* end of file */
  431.  
  432.         if(bytesget < 128)    /* if not enough for full packet, pad it to 128 with NULLs */
  433.             {
  434.             for (index =  bytesget; index < 128; index++)
  435.                 {
  436.                 sector[index] = NULL;
  437.                 }
  438.             }
  439.  
  440.         for (index = 0, n = 3; index < SECSIZE; index++, n++) /* make packet and calc checksum */
  441.             {
  442.             packet[n] = sector[index];
  443.             checksum += packet[n];
  444.             }
  445.  
  446.         checksum = checksum & 255;  /* get rid of excess bits, only need 8 */
  447.  
  448.         packet[131] = checksum; /* map it into packet */
  449.  
  450.         packet[132] = '\0';     /* we need null end of string to stop roll out later */
  451.  
  452.         return(bytesget);
  453.  
  454. }
  455.  
  456.  
  457. /*
  458. *  rxmodem
  459. *
  460. *  receive a file from caller
  461. *
  462. *
  463. *
  464. *
  465. */
  466.  
  467. int rxmodem(dirfile)
  468. char    *dirfile;
  469. {
  470.  
  471.     extern    long int strtout,timelog;
  472.     extern    char    retstr[80];
  473.     extern long fbytes,fblocks;
  474.     extern long    goodbyte;
  475.  
  476.     char blockcnt, blockcom;
  477.     char sector[SECSIZE], packet[XMSIZE];
  478.     char vline[120];
  479.  
  480.     int  index, sectot, errorcnt,checksum,errortot;
  481.     int  xrecfile;
  482.     int  rtrn;
  483.     int  timeout,blknumct;
  484.     int  n;
  485.     int  endofile;
  486.     int   percent;
  487.  
  488.     if ((xrecfile = creat(dirfile, 0x8002 )) == -1) /* open new file */
  489.         {
  490.         close(xrecfile);
  491.         return(ERROR);
  492.         }
  493.  
  494.     strtout = totsec();            /* set start time mark */
  495.     timeout = 10;
  496.     errorcnt = 0;
  497.     errortot = 0;
  498.     blknumct = 0;
  499.     sectot = 1;
  500.     blockcnt = 1;
  501.     n = 0;
  502.     goodbyte = 0L;
  503.     endofile = FALSE;
  504.  
  505.     clearmsg();
  506.     prosay(19,23,"Holding for start...  ");
  507.     while(TRUE)
  508.         {
  509.         if(miready()) break;        /* if char arrives, go */
  510.  
  511.         if(toolong(timeout))        /* if timeout, send NAK */
  512.             {
  513.             chrput(NAK);
  514.             eatbuf();
  515.             strtout = totsec();    /* restart time mark */
  516.             ++n;
  517.             if (n > 10)           /* if more than 10 NAKs, stop */
  518.                 {
  519.                 clearmsg();
  520.                 prosay(19,23,"Too many Xmodem time outs.");
  521.                 endtalk(xrecfile,4);
  522.                 return(ERROR);
  523.                 }
  524.             }
  525.  
  526.         if(!carrier())              /* if carrier lost, end Xmodem */
  527.             {
  528.             close(xrecfile);
  529.             return(ERROR);
  530.             }
  531.         if (asikbhit())           /* if keyboard hit, get it */
  532.             {
  533.             if ( getch() == ESC)          /* if ESC, stop Xmodem */
  534.                 {
  535.                 endtalk(xrecfile,1);
  536.                 return(ERROR);
  537.                 }
  538.             }
  539.         }
  540.     clearmsg();
  541.     prosay(19,23,"Initiating transfer... ");
  542.  
  543.     curset(19,23,0);
  544.  
  545.     while (TRUE)                           /* start loop */
  546.         {
  547.         if (asikbhit())          /* always let SYSOP get out */
  548.             {
  549.             if ( getch() == ESC)
  550.                 {
  551.                 endtalk(xrecfile,1);
  552.                 return(ERROR);
  553.                 }
  554.             }
  555.         clearmsg();
  556.         sprintf(vline,"Receiving block # %d ",sectot);
  557.         prosay(19,23,vline);                 /* where are we */
  558.         for (index = 0; index < XMSIZE; index++)      /* roll'em */
  559.             {
  560.             if((rtrn = readbyte(10)) == TIMEOUT)     /* get char */
  561.                 {
  562.                 clearmsg();
  563.                 sprintf(vline,"Timeout waiting for block element %d",index+1);
  564.                 prosay(19,23,vline);
  565.                 goto nakit;
  566.                 }
  567.  
  568.             else if(rtrn == ESC)    /* check SYSOP wanting out */
  569.                 {
  570.                 endtalk(xrecfile,1);
  571.                 return(ERROR);
  572.                 }
  573.  
  574.                if(!carrier())    /* keep checking that modem carrier! */
  575.                    {
  576.                    close(xrecfile);
  577.                    return(ERROR);
  578.                    }
  579.  
  580.             else
  581.                 {
  582.                 packet[index] = retstr[0];
  583.  
  584.                 if(index == 0 && retstr[0] == EOT)  /* is it end of file */
  585.                        {
  586.                        prosay(19,45," - EOT");
  587.                        endofile = TRUE;
  588.                        break;
  589.                        }
  590.  
  591.                 if(index == 0 && (retstr[0] == CTRLX)) /* is it a caller abort */
  592.                        {
  593.                        endtalk(xrecfile,2);
  594.                        return(ERROR);
  595.                        }
  596.                 }
  597.             }
  598.  
  599.         if(endofile) break;
  600.  
  601.         else if (packet[0] != SOH)    /* good packet always start with SOH */
  602.             {
  603.             prosay(19,45," - SOH error");
  604.             sprintf(vline,"SOH      ");
  605.             prosay(16,25,vline);
  606.             goto nakit;        /* if bad packet, NAK it */
  607.             }
  608.  
  609.         blockcom = ~packet[2];        /* block number compliment */
  610.  
  611.         if (packet[1] != blockcom)
  612.             {
  613.             prosay(19,45," - Block number compliment error");
  614.             sprintf(vline,"Block #  ");
  615.             prosay(16,25,vline);
  616.             goto nakit;
  617.             }
  618.  
  619.         else if (packet[1] != blockcnt)  /* are we out of sequence */
  620.             {
  621.             prosay(19,45," - Wrong block number");
  622.             sprintf(vline,"Block #  ");
  623.             prosay(16,25,vline);
  624.             ++blknumct;
  625.             goto nakit;
  626.             }
  627.         blknumct = 0;
  628.         checksum = 0;
  629.  
  630.         for (index = 3, n = 0; n < SECSIZE; index++, n++)   /* roll our own checksum calc */
  631.             {
  632.             sector[n] = packet[index];
  633.             checksum += sector[n];
  634.             }
  635.  
  636.         checksum = checksum & 255;   /* throw away excess bits, only lower 8 count */
  637.  
  638.         if (checksum != packet[131])  /* was there an error in packet xfer */
  639.             {
  640.             prosay(19,45," - Checksum error");
  641.             sprintf(vline,"Checksum ");
  642.             prosay(16,25,vline);
  643.             goto nakit;          /* packet looks bad, do it over Sam */
  644.             }
  645.  
  646.         chrput(ACK);        /* tell Sam we are ready for next blast */
  647.         eatbuf();        /* lets clean the tubes for next packet */
  648.  
  649.         if((write(xrecfile, sector, SECSIZE)) == -1)  /* looks good so write it */
  650.             {
  651.             close(xrecfile);
  652.             return(ERROR);
  653.             }
  654.  
  655.         prosay(19,45," - verified");         /* make SYSOP feel good */
  656.         sprintf(vline,"%d",sectot);
  657.         prosay(12,61,vline);
  658.         sprintf(vline,"%-4.4s","0   ");
  659.         prosay(14,61,vline);
  660.         goodbyte = sectot * 128L;
  661.         sprintf(vline,"%ld",goodbyte);
  662.         prosay(10,61,vline);
  663.         percent = (errortot * 1.0)/sectot * 100.0;
  664.         sprintf(vline,"%-3d   ",percent);
  665.         prosay(16,61,vline);
  666.  
  667.         errorcnt = 0;
  668.         blockcnt = ++sectot & 255;  /* increment sector total and block count modulo 255 */
  669.  
  670.         clearmsg();
  671.         continue;                  /* keep on rolling */
  672.  
  673. nakit:                       /* I hate'em too but sometimes... */
  674.  
  675.         if(!carrier())                  /* is Sam still there? */
  676.             {
  677.             close(xrecfile);
  678.             return(ERROR);
  679.             }
  680.         else if(++errorcnt > MAXERRORS) /* has Sam got a bad telephone line? */
  681.             {
  682.             endtalk(xrecfile,4);    /* looks bad, so save him the possible bad xfer */
  683.             return(ERROR);
  684.             }
  685.         else
  686.             {
  687.             while( miready() )        /* if chars still coming */
  688.                 {
  689.                 if (!carrier()) break;
  690.                 delay(30);              /* wait .5 sec */
  691.                 eatbuf();     /* eat buffer before retest */
  692.                 }
  693.             if (blknumct == 3 && (packet[1] == blockcnt - 1) ) chrput(ACK);   /* in case ACK was clobbered for a good block */
  694.             else chrput(NAK); /* don't mince words, tell him it was no good */
  695.             eatbuf();     /* eat buffer before retest */
  696.             ++errortot;    /* we count this one against you Sam */
  697.             sprintf(vline,"%d   ",errorcnt);
  698.             prosay(14,61,vline);
  699.             sprintf(vline,"%d   ",errortot);  /* tell SYSOP how bad it is */
  700.             prosay(14,25,vline);
  701.             percent = (errortot * 1.0)/sectot * 100.0;
  702.             sprintf(vline,"%-3d   ",percent);
  703.             prosay(16,61,vline);
  704.             clearmsg();
  705.             }
  706.         }
  707.  
  708.     close(xrecfile);
  709.  
  710.     chrput(ACK);          /* tell the other end we accepted his EOT */
  711.     chrput(ACK);
  712.     chrput(ACK);                      /* make sure he got it */
  713.  
  714.     clearmsg();
  715.     prosay(19,23,GOTITOK);            /* make SYSOP feel real good */
  716.  
  717.     sizewrit(dirfile,goodbyte); /* create data TCOMM needs to record this xfer in log */
  718.  
  719.     return(TRUE);
  720.  
  721. }
  722.  
  723.  
  724.  
  725. /*
  726.  *  endtalk
  727.  *
  728.  *
  729.  *  abornmal file transfer end, xfer terminate, send message to screen
  730. */
  731. int endtalk(fpxfer,why)
  732. int fpxfer;
  733. int why;
  734. {
  735.  
  736.     close(fpxfer);              /* close file being transferred */
  737.  
  738.     chrput(CAN);              /* send Xmodem cancel to caller */
  739.     eatbuf();              /* eat any chars coming from caller */
  740.     clearmsg();              /* get ready to give message */
  741.     if(why != 0)              /* 0 - normal end  */
  742.         {
  743.         prosay(19,23,ABORTF);
  744.         }
  745.     if(why == 1) prosay(19,40,ABORTSYS);         /* 1 - Operator abort  */
  746.     if(why == 2) prosay(19,40,ABORTUSR);         /* 2 - User abort        */
  747.     if(why == 3) prosay(19,40,ABORTEOF);         /* 3 - end of file     */
  748.     if(why == 4) prosay(19,40,ABORTXER);         /* 4 - Xmodem errors   */
  749.     if(why == 5) prosay(19,40,ABORTTO);         /* 5 - timeout */
  750.     chrput(CAN);                  /* send Xmodem cancel to caller */
  751.  
  752. }
  753.  
  754.  
  755. /*
  756.  *  prodinfo
  757.  *
  758.  *  protocol file transfer information for report screen
  759.  *  and send tty copy to caller before xfer starts
  760.  *
  761.  *
  762.  */
  763. bool prodinfo(dirfile,foo,protocol,blocklen)
  764. char *dirfile,*protocol;
  765. int blocklen,foo;
  766. {
  767.  
  768.  
  769.     extern int bps,timerem,port;
  770.     extern long xfertime;
  771.     extern long fbytes,fblocks;
  772.     extern char filedate[];
  773.  
  774.     float decblks;
  775.     char vline[RECSIZE];
  776.  
  777.     long xfermins,xfersecs;
  778.     double blkfrac;
  779.     float xferminf;
  780.  
  781.     xfermins = 0;
  782.     xfersecs = 0;
  783.     fbytes = 0;
  784.     fblocks = 0;
  785.  
  786.     fbytes = lseek(foo,0L,2);        /* get file size */
  787.     lseek(foo,0L,0);            /* go back to start of file */
  788.  
  789.     decblks = (float) (fbytes)/blocklen * 1.0 + 0.5;    /* how many blocks */
  790.     fblocks = decblks;
  791.  
  792.     asiputc(port,CR);
  793.     asiputc(port,LF);
  794.  
  795.     sprintf (vline,"Total protocol blocks: %ld",fblocks);
  796.     asiputs(port,vline);            /* tell caller */
  797.  
  798.     asiputc(port,CR);
  799.     asiputc(port,LF);
  800.     asiputc(port,CR);
  801.     asiputc(port,LF);
  802.     asiputs(port,DNLMSG);
  803.     asiputc(port,CR);
  804.     asiputc(port,LF);
  805.     asiputc(port,CR);
  806.     asiputc(port,LF);
  807.  
  808. /* now lets calculate an approximate xfer time based on imperical time tests */
  809. /* modify the 0.049 if you find your system gives different results */
  810.  
  811.     xfertime = fbytes * 0.049 * (300.0 / bps);
  812.     if (xfertime < 1) xfertime = 1L;           /* something is wrong */
  813.     xfermins = xfertime/60;
  814.     xferminf = xfertime/60.0;
  815.     xfersecs = xfertime - xfermins * 60;
  816.  
  817.     protrept();
  818.  
  819.     fdate(dirfile,filedate);
  820.     prosay( 2,25,dirfile);
  821.     prosay( 3,25,filedate);
  822.     prosay( 6,25,"Xmodem");
  823.     sprintf (vline,"%-d %-s",blocklen,"bytes");
  824.     prosay( 6,61,vline);
  825.     sprintf (vline,"%-3.2f %-s",xferminf,"min.");
  826.     prosay( 8,25,vline);
  827.     sprintf (vline,"%-ld",fbytes);
  828.     prosay(10,25,vline);
  829.     sprintf (vline,"%ld",fblocks);
  830.     prosay(12,25,vline);
  831.     sprintf (vline,"%-4.4s","0   ");
  832.     prosay(14,25,vline);
  833.     prosay(14,61,vline);
  834.     prosay(16,25,"None    ");
  835.  
  836.     return(TRUE);
  837.  
  838.  
  839. }
  840.  
  841.  
  842. /*
  843.  * prouinfo
  844.  *
  845.  * protocol upload info to fill report screen at xfer start
  846.  *
  847.  *
  848.  */
  849. bool prouinfo(dirfile,protocol,blocklen)
  850. char *dirfile, *protocol;
  851. int blocklen;
  852. {
  853.     extern int port;
  854.  
  855.     char vline[120];
  856.  
  857.     asiputc(port,CR);
  858.     asiputc(port,LF);
  859.  
  860.     asiputs(port,UPLMSG);
  861.  
  862.     asiputc(port,CR);
  863.     asiputc(port,LF);
  864.     asiputc(port,CR);
  865.     asiputc(port,LF);
  866.  
  867.     protrept();
  868.  
  869.     prosay( 2,25,dirfile);
  870.  
  871.     prosay( 6,25,"Xmodem");
  872.     prosay( 6,61,"128 bytes");
  873.     sprintf (vline,"%s","Unknown    ");
  874.     prosay( 3,25,vline);
  875.     prosay( 8,25,vline);
  876.     prosay( 8,61,vline);
  877.     prosay(10,25,vline);
  878.     prosay(12,25,vline);
  879.     sprintf (vline,"%-4.4s","0   ");
  880.     prosay(14,25,vline);
  881.     prosay(14,61,vline);
  882.     prosay(16,25,"None    ");
  883.  
  884.     return(TRUE);
  885.  
  886. }
  887.  
  888.  
  889.  
  890.  
  891.  
  892. /*
  893.  *  protrept
  894.  *
  895.  *
  896.  *  protocol progress report screen blank
  897.  *
  898.  */
  899. protrept()
  900. {
  901.     extern int display;
  902.  
  903.     if(!display) return;         /* display is off, so don't show screen */
  904.  
  905.        curtype(BLANK,6,7);
  906.        prosay( 0,0,"                        FILE TRANSFER PROGRESS REPORT                           ");
  907.        prosay( 1,0,"  …ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕª  ");
  908.        if ( xmode == 's')  {
  909.        prosay( 2,0,"  ∫        Sending file:                                                     ∫  ");
  910.        } else {
  911.        prosay( 2,0,"  ∫      Receiving file:                                                     ∫  ");
  912.        }
  913.  
  914.        prosay( 3,0,"  ∫  Created or updated:                                                     ∫  ");
  915.        prosay( 4,0,"  ÃÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕπ  ");
  916.        prosay( 5,0,"  ∫                                                                          ∫  ");
  917.        prosay( 6,0,"  ∫   Selected protocol:               Protocol packet size:                 ∫  ");
  918.        prosay( 7,0,"  ∫                                                                          ∫  ");
  919.        prosay( 8,0,"  ∫       Transfer time:                Percent transferred:                 ∫  ");
  920.        prosay( 9,0,"  ∫                                                                          ∫  ");
  921.        prosay(10,0,"  ∫   File size (bytes):                  Bytes transferred:                 ∫  ");
  922.        prosay(11,0,"  ∫                                                                          ∫  ");
  923.        prosay(12,0,"  ∫  Total file packets:                Packets transferred:                 ∫  ");
  924.        prosay(13,0,"  ∫                                                                          ∫  ");
  925.        prosay(14,0,"  ∫ Total packet errors:                 Errors this packet:                 ∫  ");
  926.        prosay(15,0,"  ∫                                                                          ∫  ");
  927.        prosay(16,0,"  ∫     Last error type:              Percent packet errors:                 ∫  ");
  928.        prosay(17,0,"  ∫                                                                          ∫  ");
  929.        prosay(18,0,"  ÃÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕπ  ");
  930.        prosay(19,0,"  ∫  Protocol message:                                                       ∫  ");
  931.        prosay(20,0,"  ÃÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕπ  ");
  932.        prosay(21,0,"  ∫      The System Operator can press ESC to abort the file transfer.       ∫  ");
  933.        prosay(22,0,"  »ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕº  ");
  934.        prosay(23,0,"                                                                                ");
  935.        curset(2,17,0);
  936.  
  937. }
  938.  
  939.  
  940.  
  941.  
  942. /*
  943.  * clearmsg
  944.  *
  945.  * clear protocol message on progress screen
  946.  *
  947.  */
  948. int clearmsg()
  949. {
  950.     prosay(19,23,"                                                    ");
  951.  
  952. }
  953.  
  954.  
  955. /*
  956.  *  xferread()
  957.  *
  958.  *  read file transfer information from default drive/directory
  959.  *  for protocol use
  960.  *
  961.  *  xmode: r = receive from caller
  962.  *       s = send file to caller
  963.  *  xfilenam: filename without directory path or drive for display only
  964.  *  xdirfile: path and name of file to transfer (i.e., c:\files\filename)
  965.  *          protocols that accept wildcards should accept and expand
  966.  *          the filename in this protocol somewhere
  967.  *  portnum: 1 = COM1     (the selected one is initialized - just start
  968.  *         2 = COM2      communicating with it)
  969.  *  bps = communications speed in bits per second to calculate xfer time
  970.  *  parity = parity of communications line (Xmodem only allows n - none)
  971.  *  display: 0 = display is off and no information should be sent to screen
  972.  *         1 = display is on and info should be sent to screen
  973.  *  cfgcolor = foreground color in caller mode
  974.  *           set in TCOMM configuration profile
  975.  *
  976.  *  Returns: FALSE if file error
  977.  *         TRUE if all ok
  978.  */
  979. int xferread()
  980. {
  981.  
  982.     extern char xmode,xdirfile[60],xfilenam[60],kparity[10];
  983.     extern int display,cfgcolor,wordlen,port,parity,bps;
  984.  
  985.     FILE    *fpstat;
  986.  
  987.  
  988.     if((fpstat=fopen(FILEXFER,"r"))==NULL)
  989.         {
  990.         clrerr(fpstat);
  991.         return(FALSE);
  992.         }
  993.     if((fscanf(fpstat,"%c %s %s %d %s %d %d",&xmode,xdirfile,portnum,&bps,kparity,&display,&cfgcolor)) != 7)
  994.         {
  995.         fclose(fpstat);
  996.         clrerr(fpstat);
  997.         return(FALSE);
  998.  
  999.         }
  1000.     if((fclose(fpstat))==ERROR)
  1001.         {
  1002.         clrerr(fpstat);
  1003.         return(FALSE);
  1004.         }
  1005.     if(portnum[3] == '2') port = 1;
  1006.     else port = 0;
  1007.  
  1008.     if (kparity[0] == 'n')
  1009.         {
  1010.         parity = NONE;
  1011.         wordlen = 8;
  1012.         stopbits = 1;
  1013.         }
  1014.     else
  1015.         {
  1016.         wordlen = 7;
  1017.         stopbits = 1;
  1018.         if (kparity[0] == 'e') parity = EVEN;
  1019.         if (kparity[0] == 'o') parity = ODD;
  1020.         }
  1021.  
  1022.     unlink(FILEXFER);
  1023.     return(TRUE);
  1024.  
  1025. }
  1026.  
  1027.  
  1028.  
  1029. /*
  1030.  *  sizewrit(dirfile,bytes)
  1031.  *
  1032.  *  write filename and bytes of file transfer to default drive/directory
  1033.  *  for main program to pickup
  1034.  *
  1035.  *  dirfile:  filename preceeded by path
  1036.  *
  1037.  *  bytes:  0 if file transfer abort
  1038.  *        # if transfer success
  1039.  *
  1040.  *  Returns: FALSE if file error
  1041.  *         TRUE if all ok
  1042.  */
  1043. int sizewrit(dirfile,bytes)
  1044. char *dirfile;
  1045. long bytes;
  1046. {
  1047.  
  1048.     FILE    *fpstat;
  1049.  
  1050.  
  1051.        if((fpstat=fopen(FILESIZE,"w"))==NULL)
  1052.            {
  1053.            clrerr(fpstat);
  1054.            return(FALSE);
  1055.            }
  1056.        fprintf(fpstat,"%s %7ld -%c",dirfile,bytes,CR);      /* use - for date */
  1057.        if((fclose(fpstat))==ERROR)
  1058.            {
  1059.            clrerr(fpstat);
  1060.            }
  1061.  
  1062.     return(TRUE);
  1063.  
  1064.  
  1065. }
  1066.  
  1067.  
  1068.  
  1069. /*
  1070. *    F D A T E
  1071. *
  1072. *    Return file creation date/time
  1073. *
  1074. *
  1075. */
  1076. fdate(fname,str)
  1077. char *fname,*str;
  1078. {
  1079.  
  1080.     struct TIMEDATE td;                /*  Greenleaf function */
  1081.  
  1082.     if (( getfstamp( &td,fname)) != 0) return(0);  /* return false if not */
  1083.                            /* able to get file date */
  1084.  
  1085.     sprintf(str,"%02.2d/%02.2d/%-4d - %002.2d:%002.2d",
  1086.           td.month,td.day,td.year,td.hours,td.minutes);
  1087.     return(1);
  1088.  
  1089. }
  1090.